import virtkey

import py3func
import executor.keysym as keysym
from executor.abstractcmd import KeyCmd, Enum_Key_Type
from cui import Enum_Btn_Status

LOG = py3func.make_logging(__file__)
try:
    VirtKeyObject = virtkey.virtkey()
except virtkey.error as e:
    LOG.exception("Fail to init virtkey().\n")
    VirtKeyObject = None

class Key(KeyCmd):
    def __init__(self):
        super().__init__()

        # @attribute
        self._vk = VirtKeyObject  # 调用全局virtkey对象

    def check_keycode(self, key_name):
        pass

    def update_keycode(self, new_key):
        self.check_keycode(new_key)  # 合法性验证
        self.name = new_key

class Key_Char(Key):
    key_type = Enum_Key_Type["key_char"]

    def __init__(self, char=None):
        super().__init__()
        self.name = char

    def _spcial_key_check(self, key_name):  # depressed, replace by stand XML escape characters
        """ if no need to change the key, return None """
        # Unxml_Key
        if key_name in keysym.Unxml_Key:
            return keysym.Unxml_Key[key_name]

    def key_exec(self, key_status):
        if not self.name:
            raise Exception("The key code is None")
        """
        # 处理特殊字符：depressed —— 使用xml标准转义字符
        status = self._spcial_key_check(self.name)
        if status:
            self.name = status
        """

        # 处理非字符按键
        # if py3func.isAscii(self.name):
        if self.name not in keysym.Code_Key:
            func_press = lambda char: self._vk.press_unicode(ord(char))
            func_release = lambda char: self._vk.release_unicode(ord(char))
        else:
            # LOG.debug("切换使用virtkey.press_keycode()打印不可见字符[%s]" % self.name)
            func_press = lambda name: self._vk.press_keycode(keysym.Code_Key[name])
            func_release = lambda name: self._vk.release_keycode(keysym.Code_Key[name])

        if key_status != Enum_Btn_Status["released"]:
            func_press(self.name)
        else:
            func_release(self.name)


class Key_Func(Key):
    key_type = Enum_Key_Type["key_func"]

    def __init__(self, func_key=None):
        super().__init__()
        self.check_keycode(func_key)

    def check_keycode(self, func_name):
        if func_name is not None:  # 切换打印字符
            if func_name not in keysym.Function_Key:
                raise Exception("Unknown Function_Key [%s]" % func_name)
            self.name = func_name

    def key_exec(self, key_status):
        key_code = keysym.Function_Key[self.name]
        if key_status != Enum_Btn_Status["released"]:
            self._vk.press_keysym(key_code)
        else:
            self._vk.release_keysym(key_code)


class Key_Mode(Key):
    """ 不同于Key_Char，可以动态改变键对象的name；对于isSticky==True的对象，需要在对象中记录黏滞状态 """
    key_type = Enum_Key_Type["key_mode"]

    def __init__(self, mode_key: str):
        super().__init__()
        self.check_keycode(mode_key)
        self.name = mode_key

    def check_keycode(self, mode_key):
        if mode_key not in keysym.Modifier_Key:
            raise Exception("Unkown Modifier_Key [%s]" % mode_key)

    def key_exec(self, key_status):
        """ 不同于 Key_Char，不支持使用时切换按键键值 """
        LOG.debug("Mode_key[%s] execute, status is: %d" % (self.name, key_status))
        if key_status != Enum_Btn_Status["released"]:
            self._vk.lock_mod(keysym.Modifier_Key[self.name])
        else:
            self._vk.unlock_mod(keysym.Modifier_Key[self.name])


class Key_Comb(Key):
    """ 通过判断特定辅助键的状态，执行动作 """
    pass
